#include <jni.h>
#include <string>
#include "dalvik.h"






static void* dvm_dlsym(void *hand, const char *name) {
    void* ret = dlsym(hand, name);
    char msg[1024] = { 0 };
    snprintf(msg, sizeof(msg) - 1, "0x%x", ret);
    LOGD("%s = %s\n", name, msg);
    return ret;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zgkxzx_myfix_HandleNative_setFieldFlag(JNIEnv *env, jclass type, jobject field) {

    // TODO
    LOGI("Java_com_zgkxzx_myfix_HandleNative_setFieldFlag.....");
    Field* dalvikField = (Field*) env->FromReflectedField(field);
    dalvikField->accessFlags = dalvikField->accessFlags & (~ACC_PRIVATE)
                               | ACC_PUBLIC;
    LOGD("dalvik_setFieldFlag: %d ", dalvikField->accessFlags);

}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zgkxzx_myfix_HandleNative_init(JNIEnv *env, jclass type, jint appVersion) {
    // TODO

    LOGI("Java_com_zgkxzx_myfix_HandleNative_init.....");
    void* dvm_hand = dlopen("libdvm.so", RTLD_NOW);
    int apilevel = appVersion;

    if (dvm_hand) {
        dvmDecodeIndirectRef_fnPtr = (dvmDecodeIndirectRef_func)dvm_dlsym(dvm_hand,
                                               apilevel > 10 ?
                                               "_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :
                                               "dvmDecodeIndirectRef");
        if (!dvmDecodeIndirectRef_fnPtr) {
            LOGI("dvmDecodeIndirectRef_fnPtr JNI_FALSE");
            return JNI_FALSE;
        }
        dvmThreadSelf_fnPtr = (dvmThreadSelf_func)dvm_dlsym(dvm_hand,
                                        apilevel > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");
        if (!dvmThreadSelf_fnPtr) {
            LOGI("dvmThreadSelf_fnPtr JNI_FALSE");
            return JNI_FALSE;
        }
        jclass clazz = env->FindClass("java/lang/reflect/Method");
        jClassMethod = env->GetMethodID(clazz, "getDeclaringClass",
                                        "()Ljava/lang/Class;");
        LOGI("jClassMethod JNI_TRUE");
        return JNI_TRUE;
    } else {
        LOGI("JNI_FALSE");
        return JNI_FALSE;
    }
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zgkxzx_myfix_HandleNative_replaceMethod(JNIEnv *env, jclass type, jobject src,
                                                 jobject dest) {
    LOGI("Java_com_zgkxzx_myfix_HandleNative_replaceMethod.....");
    // TODO

    jobject clazz = env->CallObjectMethod(dest, jClassMethod);
    ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef_fnPtr(
            dvmThreadSelf_fnPtr(), clazz);
    clz->status = CLASS_INITIALIZED;

    Method* meth = (Method*) env->FromReflectedMethod(src);
    Method* target = (Method*) env->FromReflectedMethod(dest);
    LOGD("dalvik Method: %s", meth->name);
    LOGD("dalvik target Method: %s", target->name);

	meth->clazz = target->clazz;
    meth->accessFlags |= ACC_PUBLIC;
    meth->methodIndex = target->methodIndex;
    meth->jniArgInfo = target->jniArgInfo;
    meth->registersSize = target->registersSize;
    meth->outsSize = target->outsSize;
    meth->insSize = target->insSize;

    meth->prototype = target->prototype;
    meth->insns = target->insns;
    meth->nativeFunc = target->nativeFunc;

}


